{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "509ba7d0-8541-4298-af52-0b536e78699f",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Sliding Window Attention is enabled but not implemented for `sdpa`; unexpected results may be encountered.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ae8fdb22ff74470f833b74927f97cd40",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/2 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting `pad_token_id` to `eos_token_id`:151643 for open-end generation.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "嗯，用户让我帮他写一个二分查找法。首先，我得想想二分查找的基本原理。二分查找，也叫折半查找，它在有序数组中快速定位目标值的位置，时间复杂度是O(log n)，效率很高。那用户可能需要的是Python代码，或者具体的应用场景？\n",
      "\n",
      "用户可能不太清楚二分查找的步骤，或者想用它来解决某个问题。也许他正在学习算法，或者遇到了需要高效查找的问题。所以，我应该详细地解释二分查找的步骤，并提供一个Python实现的示例。\n",
      "\n",
      "首先，我得确保数组是有序的，因为二分查找只能在有序数组中使用。然后，初始化两个指针，left和right，分别指向数组的开头和结尾。接着，计算中间的位置mid，比较目标值和数组[mid]的值。如果目标值小于数组[mid]，就调整right指针；否则，调整left指针。重复这个过程，直到找到目标值或者确定其不存在。\n",
      "\n",
      "我应该用一个例子来说明，比如查找数字5在数组中的位置。这样用户更容易理解。同时，代码要清晰，注释也要到位，方便用户理解每一步的作用。\n",
      "\n",
      "另外，我得考虑边界条件，比如数组为空的情况，或者目标值在数组最左或最右的情况。这些情况都需要在代码中处理，避免运行时错误。\n",
      "\n",
      "最后，我应该总结一下这种方法的时间复杂度和空间复杂度，以及它的适用场景，这样用户能更好地理解什么时候使用这种方法，以及它的优缺点。\n",
      "</think>\n",
      "\n",
      "好的，以下是一个使用二分查找法的Python示例：\n",
      "\n",
      "```python\n",
      "def binary_search(arr, target):\n",
      "    left = 0\n",
      "    right = len(arr) - 1\n",
      "    \n",
      "    while left <= right:\n",
      "        mid = (left + right) // 2\n",
      "        \n",
      "        if arr[mid] == target:\n",
      "            return mid\n",
      "        elif arr[mid] < target:\n",
      "            left = mid + 1\n",
      "        else:\n",
      "            right = mid - 1\n",
      "    \n",
      "    return -1  # 目标值不在数组中\n",
      "\n",
      "# 示例用法：\n",
      "arr = [1, 3, 5, 7, 9, 11, 13, 15]\n",
      "target = 7\n",
      "\n",
      "index = binary_search(arr, target)\n",
      "if index != -1:\n",
      "    print(f\"目标值{target}在数组中的索引是：{index}\")\n",
      "else:\n",
      "    print(f\"目标值{target}不在数组中\")\n",
      "```\n",
      "\n",
      "### 代码解释：\n",
      "1. **函数定义**：`binary_search(arr, target)`，接受一个有序数组 `arr` 和目标值 `target`。\n",
      "2. **初始化指针**：`left` 初始化为数组的开头索引，`right` 初始化为数组的结尾索引。\n",
      "3. **循环查找**：使用 `while` 循环，当 `left` 小于等于 `right` 时，计算中间索引 `mid`。\n",
      "4. **比较目标值**：\n",
      "   - 如果 `arr[mid]` 等于 `target`，返回 `mid`（找到目标值）。\n",
      "   - 如果 `arr[mid]` 小于 `target`，调整 `left` 指针向右移动。\n",
      "   - 如果 `arr[mid]` 大于 `target`，调整 `right` 指针向左移动。\n",
      "5. **未找到目标值**：如果循环结束后仍未找到，返回 `-1` 表示目标值不在数组中。\n",
      "\n",
      "### 示例用法说明：\n",
      "- **数组**：`arr = [1, 3, 5, 7, 9, 11, 13, 15]`\n",
      "- **目标值**：`target = 7`\n",
      "- **返回结果**：`index = 3`，因为 `7` 在数组中的索引是 3。\n",
      "\n",
      "### 输出结果：\n",
      "```\n",
      "目标值7在数组中的索引是：3\n",
      "```\n",
      "\n",
      "这个示例展示了如何使用二分查找法快速定位目标值的位置。二分查找法的时间复杂度为 O(log n)，其中 n 是数组的长度，适用于处理大型数据集。\n"
     ]
    }
   ],
   "source": [
    "from modelscope import AutoModelForCausalLM, AutoTokenizer\n",
    "model_name = \"/root/autodl-tmp/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n",
    "model = AutoModelForCausalLM.from_pretrained(\n",
    "    model_name,\n",
    "    torch_dtype=\"auto\",\n",
    "    device_map=\"cuda\" # auto\n",
    ")\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
    "prompt = \"帮我写一个二分查找法\"\n",
    "messages = [\n",
    "    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
    "    {\"role\": \"user\", \"content\": prompt}\n",
    "]\n",
    "text = tokenizer.apply_chat_template(\n",
    "    messages,\n",
    "    tokenize=False,\n",
    "    add_generation_prompt=True\n",
    ")\n",
    "model_inputs = tokenizer([text], return_tensors=\"pt\").to(model.device)\n",
    "generated_ids = model.generate(\n",
    "    **model_inputs,\n",
    "    max_new_tokens=2000\n",
    ")\n",
    "generated_ids = [\n",
    "    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)\n",
    "]\n",
    "response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]\n",
    "print(response)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
